package com.fm.parser.excel;

import com.fm.base.annotation.UnThreadSafe;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.Closeable;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;

@UnThreadSafe
public class Excel2007Writer implements Closeable {
	private SXSSFWorkbook book;
	private SXSSFSheet sheet;
	private CellStyle dateStyle;
	private OutputStream stream;
	private int curRow = 0;

	public Excel2007Writer(String path) throws IOException {
		this(path, "Sheet1");
	}

	public Excel2007Writer(String path, String sheetName) throws IOException {
		this(new FileOutputStream(path), sheetName);
	}

	public Excel2007Writer(OutputStream stream, String sheetName) {
		this.book = new SXSSFWorkbook(100);
		this.sheet = book.createSheet(sheetName);
		this.dateStyle = book.createCellStyle();
		this.dateStyle.setDataFormat((short) 22);
		this.stream = stream;
	}

	public void appendRow(List<? extends Object> line) {
		SXSSFRow row = sheet.createRow(curRow++);
		int i = 0;
		for(Object obj : line) {
			Cell cell;
			if (obj == null) {
				row.createCell(i, CellType.BLANK);
			} else if (obj instanceof String) {
				cell = row.createCell(i, CellType.STRING);
				cell.setCellValue((String) obj);
			} else if (obj instanceof Number) {
				cell = row.createCell(i, CellType.NUMERIC);
				cell.setCellValue(((Number) obj).doubleValue());
			} else if (obj instanceof Date) {
				cell = row.createCell(i, CellType.NUMERIC);
				cell.setCellStyle(dateStyle);
				cell.setCellValue((Date) obj);
			} else if (obj instanceof Boolean) {
				cell = row.createCell(i, CellType.BOOLEAN);
				cell.setCellValue((boolean) obj);
			} else if (obj instanceof RichTextString) {
				cell = row.createCell(i, CellType.STRING);
				cell.setCellValue((RichTextString) obj);
			} else {
				cell = row.createCell(i, CellType.STRING);
				cell.setCellValue(obj.toString());
			}
			i++;
		}
	}

	/**
	 * 设定合并单元格区域范围
	 *
	 * @param rowFrom    0-based
	 * @param rowTo      0-based
	 * @param columnFrom 0-based
	 * @param columnTo   0-based
	 */
	public void mergeCells(int rowFrom, int rowTo, int columnFrom, int columnTo) {
		CellRangeAddress address = new CellRangeAddress(rowFrom, rowTo, columnFrom, columnTo);
		sheet.addMergedRegion(address);
	}

	public void close() throws IOException {
		book.write(stream);
		book.close();
		stream.close();
	}
}